home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / DataScope 2.0.3 / DataScope2l / TCPSource / util.c < prev   
Encoding:
C/C++ Source or Header  |  1994-05-04  |  21.9 KB  |  1,023 lines  |  [TEXT/MPS ]

  1. /*
  2. *   Util.c
  3. *   utility library for use with the Network kernel
  4. *
  5. */
  6. #include "stdio.h"
  7. #include "memory.h"
  8. #include "whatami.h"
  9. #include "hostform.h"
  10.  
  11. #ifdef PC
  12. #include "string.h"
  13. #else
  14. #ifdef AZTEC
  15. #define strchr(A,B) index(A,B)
  16. #endif
  17. #endif
  18.  
  19. char                             /* special function types */
  20.             *neterrstring();
  21. int32 time();                    /* don't forget this sucker! */
  22.  
  23. extern struct machinfo *Sns;
  24.  
  25. static unsigned char
  26.             *Ssstemps[] = {
  27.             "capfile",
  28.             "hp.out",
  29.             "ps.out",
  30.             "tek.out"
  31.             };
  32.  
  33. char Sptypes[NPORTS];        /* port types assigned for session use */
  34.  
  35.  
  36. extern struct config Scon;        /* hardware configuration */
  37.  
  38. #define NTIMES 30
  39.  
  40. /*
  41. *  timer queue of events which will be placed into the event queue
  42. *  when the time is up.
  43. */
  44. struct {
  45.     unsigned char
  46.         eclass,                    /* event queue data */
  47.         event;
  48.     int
  49.         next,                    /* next item in list */
  50.         idata;
  51.     int32 when;                /* when timer is to go off */
  52. } Stq[NTIMES];
  53.  
  54. static int
  55.         domwait = 0,            /* is domain waiting for nameserver? */
  56.         Stfirst,Stfree;            /* pointers for timer queue */
  57.  
  58. #define PFTP 1
  59. #define PRCP 2
  60. #define PDATA 3
  61. #define PDOMAIN 4
  62.  
  63. /************************************************************************/
  64. /*  Snetinit
  65. *   Do network initialization for those who want the defaults all
  66. *   set for them.  Recommend that neterrchange be called before
  67. *   initializing network stuff.
  68. */
  69. Snetinit()
  70.     {
  71.     int i;
  72.  
  73. /*
  74. *  set up the file names
  75. */
  76.     Scon.capture = Ssstemps[0];
  77.     Scon.hpfile = Ssstemps[1];
  78.     Scon.psfile = Ssstemps[2];
  79.     Scon.tekfile = Ssstemps[3];
  80.  
  81.     neteventinit();                /* initializes for error messages to count */
  82.  
  83.     for (i=0; i<NPORTS; i++)
  84.         Sptypes[i] = -1;            /* clear port type flags */
  85.  
  86.     for (i=0; i<NTIMES; i++)
  87.         Stq[i].next = i+1;            /* load linked list */
  88.     Stq[NTIMES-1].next = -1;        /* anchor end */
  89.     Stfirst = -1;
  90.     Stfree = 0;
  91.  
  92.     if (!Sreadhosts()) {             /* parses config file */
  93. #ifdef PC
  94.         netparms(Scon.irqnum,Scon.address,Scon.ioaddr);
  95. #endif
  96.         netconfig(Scon.hw);
  97.  
  98.         if (!netinit()) {            /* starts up hardware */
  99. /*
  100. *  Check for the need to RARP and do it
  101. */
  102.             netgetip(Scon.myipnum);    /* get stored ip num */
  103.             if (comparen(Scon.myipnum,"RARP",4)) {    /* need RARP */
  104.                 if (netgetrarp())    /* stores in nnipnum at lower layer */
  105.                     return(-2);
  106.                 netgetip(Scon.myipnum);
  107.                 netsetip(Scon.myipnum);    
  108.             }
  109.  
  110. /*
  111. *  Give the lower layers a chance to check to see if anyone else
  112. *  is using the same ip number.  Usually generates an ARP packet.
  113. */
  114.             netarpme(Scon.myipnum);        
  115.  
  116.             Ssetgates();            /* finishes IP inits */
  117.             Stask();
  118.             return(0);
  119.         }
  120.     }
  121.  
  122.     return(-1);    
  123. }
  124.  
  125. /**************************************************************************/
  126. /*  Snetopen
  127. *
  128. *   Takes a pointer to a machine record, looked up with Sgethost and
  129. *   initiates the TCP open call.
  130. *
  131. */
  132. Snetopen(m,tport)
  133.     struct machinfo *m;
  134.     int tport;
  135.     {
  136.     int j;
  137.  
  138.     if (!m || m->mstat < HAVEIP)
  139.         return(-1);
  140.  
  141.     j = netxopen(m->hostip,tport,m->retrans,m->mtu,m->maxseg,m->window);
  142.                                     /* do the open call */
  143.  
  144.     if (j >= 0) {
  145.         Sptypes[j] = -1;            /* is allocated to user */
  146.         Stimerset(CONCLASS,CONFAIL,j,m->conto);
  147.         Stimerset(SCLASS,RETRYCON,j,m->retrans/TICKSPERSEC+2);
  148.     }
  149.  
  150.     return(j);
  151. }
  152.  
  153.  
  154. /**************************************************************************/
  155. /*
  156. *  special domain data structures
  157. */
  158. #define DOMSIZE 512                /* maximum domain message size to mess with */
  159.  
  160. /*
  161. *  Header for the DOMAIN queries
  162. *  ALL OF THESE ARE BYTE SWAPPED QUANTITIES!
  163. *  We are the poor slobs who are incompatible with the world's byte order
  164. */
  165. struct dhead {
  166. uint16
  167.     ident,                /* unique identifier */
  168.     flags,    
  169.     qdcount,            /* question section, # of entries */
  170.     ancount,            /* answers, how many */
  171.     nscount,            /* count of name server RRs */
  172.     arcount;            /* number of "additional" records */
  173. };
  174.  
  175. /*
  176. *  flag masks for the flags field of the DOMAIN header
  177. */
  178. #define DQR        0x8000            /* query = 0, response = 1 */
  179. #define DOPCODE    0x7100            /* opcode, see below */
  180. #define DAA        0x0400            /* Authoritative answer */
  181. #define DTC        0x0200            /* Truncation, response was cut off at 512 */
  182. #define DRD        0x0100            /* Recursion desired */
  183. #define DRA        0x0080            /* Recursion available */
  184. #define DRCODE    0x000F            /* response code, see below */
  185.  
  186.                                 /* opcode possible values: */
  187. #define DOPQUERY    0            /* a standard query */
  188. #define DOPIQ        1            /* an inverse query */
  189. #define DOPCQM        2            /* a completion query, multiple reply */
  190. #define DOPCQU        3             /* a completion query, single reply */
  191. /* the rest reserved for future */
  192.  
  193.                                 /* legal response codes: */
  194. #define DROK    0                /* okay response */
  195. #define DRFORM    1                /* format error */
  196. #define DRFAIL    2                /* their problem, server failed */
  197. #define DRNAME    3                /* name error, we know name doesn't exist */
  198. #define DRNOPE    4                /* no can do request */
  199. #define DRNOWAY    5                /* name server refusing to do request */
  200.  
  201. #define DTYPEA    1                /* host address resource record (RR) */
  202. #define DTYPEPTR    12            /* a domain name ptr */
  203.  
  204. #define DIN        1                /* ARPA internet class */
  205. #define DWILD    255                /* wildcard for several of the classifications */
  206.  
  207. /*
  208. *  a resource record is made up of a compressed domain name followed by
  209. *  this structure.  All of these ints need to be byteswapped before use.
  210. */
  211. struct rrpart {
  212.     uint16
  213.         rtype,                    /* resource record type = DTYPEA */
  214.         rclass;                    /* RR class = DIN */
  215.     uint32
  216.         rttl;                    /* time-to-live, changed to 32 bits */
  217.     uint16
  218.         rdlength;                /* length of next field */
  219.     uint8
  220.         rdata[DOMSIZE];            /* data field */
  221. };
  222.  
  223. /*
  224. *  data for domain name lookup
  225. */
  226. struct useek {
  227.     struct dhead h;
  228.     uint8 x[DOMSIZE];
  229. } question;
  230.  
  231. qinit()
  232.     {
  233.     question.h.flags = intswap(DRD);
  234.     question.h.qdcount = intswap(1);
  235.     question.h.ancount = 0;
  236.     question.h.nscount = 0;
  237.     question.h.arcount = 0;
  238. }
  239.  
  240.  
  241. /*********************************************************************/
  242. /*  packdom
  243. *   pack a regular text string into a packed domain name, suitable
  244. *   for the name server.
  245. */
  246. packdom(dst,src)
  247.     char *src,*dst;
  248.     {
  249.     char *p,*q,*savedst;
  250.     int i,dotflag,defflag;
  251.  
  252.     p = src;
  253.     dotflag = defflag = 0;
  254.     savedst = dst;
  255.  
  256.     do {                            /* copy whole string */
  257.         *dst = 0;
  258.         q = dst + 1;
  259.  
  260. /*
  261. *  copy the next label along, char by char until it meets a period or
  262. *  end of string.
  263. */
  264.         while (*p && (*p != '.')) 
  265.             *q++ = *p++;
  266.  
  267.         i = p - src;
  268.         if (i > 0x3f)
  269.             return(-1);
  270.         *dst = i;
  271.         *q = 0;
  272.  
  273.         if (*p) {                    /* update pointers */
  274.             dotflag = 1;
  275.             src = ++p;
  276.             dst = q;
  277.         }
  278.         else if (!dotflag && !defflag && Scon.defdom) {
  279.             p = Scon.defdom;        /* continue packing with default */
  280.             defflag = 1;
  281.             src = p;
  282.             dst = q;
  283.             netposterr(801);        /* using default domain */
  284.         }
  285.  
  286.     } while (*p);
  287.  
  288.     q++;
  289.     return(q-savedst);            /* length of packed string */
  290. }
  291.  
  292. /*********************************************************************/
  293. /*  unpackdom
  294. *  Unpack a compressed domain name that we have received from another
  295. *  host.  Handles pointers to continuation domain names -- buf is used
  296. *  as the base for the offset of any pointer which is present.
  297. *  returns the number of bytes at src which should be skipped over.
  298. *  Includes the NULL terminator in its length count.
  299. */
  300. unpackdom(dst,src,buf)
  301.     char *src,*dst,buf[];
  302.     {
  303.     int i,j,retval;
  304.     char *savesrc;
  305.  
  306.     savesrc = src;
  307.     retval = 0;
  308.  
  309.     while (*src) {
  310.         j = *src;
  311.  
  312.         while ((j & 0xC0) == 0xC0) {
  313.             if (!retval)
  314.                 retval = src-savesrc+2;
  315.             src++;
  316.             src = &buf[(j & 0x3f)*256+*src];        /* pointer dereference */
  317.             j = *src;
  318.         }
  319.  
  320.         src++;
  321.         for (i=0; i < (j & 0x3f) ; i++)
  322.             *dst++ = *src++;
  323.  
  324.         *dst++ = '.';
  325.     }
  326.  
  327.     *(--dst) = 0;            /* add terminator */
  328.     src++;                    /* account for terminator on src */
  329.  
  330.     if (!retval)
  331.         retval = src-savesrc;
  332.  
  333.     return(retval);
  334. }
  335.  
  336. /*********************************************************************/
  337. /*  sendom
  338. *   put together a domain lookup packet and send it
  339. *   uses port 53
  340. */
  341. sendom(s,towho,num)
  342.     char *s,*towho;
  343.     int16 num;
  344.     {
  345.     uint16 i,ulen;
  346.     uint8 *psave,*p;
  347.  
  348.     psave = (uint8 *)question.x;
  349.  
  350.     i = packdom(question.x,s);
  351.  
  352. /*
  353. *  load the fields of the question structure a character at a time so
  354. *  that 68000 machines won't barf.
  355. */
  356.     p = &question.x[i];
  357.     *p++ = 0;                /* high byte of qtype */
  358.     *p++ = DTYPEA;            /* number is < 256, so we know high byte=0 */
  359.     *p++ = 0;                /* high byte of qclass */
  360.     *p++ = DIN;                /* qtype is < 256 */
  361.  
  362.     question.h.ident = intswap(num);
  363.     ulen = sizeof(struct dhead)+(p-psave);
  364.  
  365.     netusend(towho,53,997,&question,ulen);
  366.     
  367. }
  368.  
  369. /**************************************************************************/
  370. /*  Sdomain
  371. *   DOMAIN based name lookup
  372. *   query a domain name server to get an IP number
  373. *    Returns the machine number of the machine record for future reference.
  374. *   Events generated will have this number tagged with them.
  375. *   Returns various negative numbers on error conditions.
  376. */
  377. Sdomain(mname)
  378.     char *mname;
  379.     {
  380.     struct machinfo *m;
  381.  
  382.     if (!Sns)                             /* no nameserver, give up now */
  383.         return(-1);
  384.  
  385.     while (*mname && *mname < 33)        /* kill leading spaces */
  386.         mname++;
  387.     if (!(*mname))
  388.         return(-1);
  389.  
  390.     if (!(m = Smadd(mname)))
  391.         return(-1);                        /* adds the number to the machlist */
  392.  
  393.     if (domwait < Scon.domto)
  394.         domwait = Scon.domto;            /* set the minimum timeout */
  395.  
  396.     qinit();                            /* initialize some flag fields */
  397.  
  398.     netulisten(997);                    /* pick a return port */
  399.     if (!m->hname)
  400.         m->hname = m->sname;            /* copy pointer to sname */
  401.  
  402.     sendom(m->hname,Sns->hostip,m->mno);    /* try UDP */
  403.  
  404.     Stimerset(SCLASS,UDPTO,m->mno,domwait);    /* time out quickly first time */
  405.     m->mstat = UDPDOM;
  406.  
  407.     return(m->mno);
  408.  
  409. }
  410.  
  411. /*********************************************************************/
  412. /*  getdomain
  413. *   Look at the results to see if our DOMAIN request is ready.
  414. *   It may be a timeout, which requires another query.
  415. */
  416.  
  417. udpdom()
  418.     {
  419.     struct machinfo *m;
  420.     int i,uret,num;
  421.     char *p;
  422.  
  423.     uret = neturead(&question);
  424.  
  425.     if (uret < 0) {
  426. /*        netputevent(USERCLASS,DOMFAIL,-1);  */
  427.         return(-1);
  428.     }
  429.  
  430.     num = intswap(question.h.ident);        /* get machine number */
  431. /*
  432. *  check to see if the necessary information was in the UDP response
  433. */
  434.     m = Slooknum(num);                /* get machine info record */
  435.     if (!m) {
  436.         netputevent(USERCLASS,DOMFAIL,num);
  437.         return(-1);
  438.     }
  439.  
  440. /*
  441. *  got a response, so reset timeout value to recommended minimum
  442. */
  443.     domwait = Scon.domto;
  444.  
  445.     i = ddextract(&question,m->hostip);
  446.  
  447.     switch (i) {
  448.         case 3:                        /* name does not exist */
  449.             netposterr(802);
  450.             p = neterrstring(-1);
  451.             strncpy(p,m->hname,78);        /* what name */
  452.             netposterr(-1);
  453.             netputevent(USERCLASS,DOMFAIL,num);
  454.             Stimerunset(SCLASS,UDPTO,num);
  455.             return(-1);
  456.         case 0:                        /* we found the IP number */
  457.             Stimerunset(SCLASS,UDPTO,num);
  458.             m->mstat = DOM;            /* mark that we have it from DOMAIN */
  459.             netputevent(USERCLASS,DOMOK,num);
  460.             return(0);
  461.         case -1:                    /* strange return code from ddextract */
  462.             netposterr(803);
  463.             break;
  464.         default:
  465.             netposterr(804);
  466.             break;
  467.     }
  468.  
  469.     return(0);
  470.  
  471. }
  472.  
  473. /**************************************************************************/
  474. /*  domto
  475. *   Handle time out for DOMAIN name lookup
  476. *   Retry as many times as recommended by config file
  477. */
  478. domto(num)
  479.     int num;
  480.     {
  481.     struct machinfo *m;
  482.  
  483.     m = Slooknum(num);
  484.     if (!m)
  485.         return(-1);
  486.  
  487.     if (m->mstat > UDPDOM + Scon.ndom) {    /* permanent timeout */
  488.         netputevent(USERCLASS,DOMFAIL,num);
  489.         return(-1);
  490.     }
  491.     else
  492.         m->mstat++;            /* one more timeout */
  493.     
  494.     if (domwait < 20)        /* exponential backoff */
  495.         domwait <<= 1;
  496.  
  497.     Snewns();                /* rotate to next nameserver */
  498.  
  499.     qinit();
  500.  
  501.     netulisten(997);                    /* pick a return port */
  502.     sendom(m->hname,Sns->hostip,num);        /* try UDP */
  503.  
  504.     Stimerset(SCLASS,UDPTO,num,domwait);    /* time out more slowly */
  505.  
  506.     return(num);
  507.     
  508. }
  509.  
  510. /*********************************************************************/
  511. /*  ddextract
  512. *   extract the ip number from a response message.
  513. *   returns the appropriate status code and if the ip number is available,
  514. *   copies it into mip
  515. */
  516. ddextract(qp,mip)
  517.     struct useek *qp;
  518.     unsigned char *mip;
  519.     {
  520.     uint16 i,j,nans,rcode;
  521.     struct rrpart *rrp;
  522.     uint8 *p,space[260];
  523.  
  524.     nans = intswap(qp->h.ancount);                /* number of answers */
  525.     rcode = DRCODE & intswap(qp->h.flags);        /* return code for this message*/
  526.     if (rcode > 0)
  527.         return(rcode);
  528.  
  529.     if (nans > 0 &&                                /* at least one answer */
  530.         (intswap(qp->h.flags) & DQR)) {            /* response flag is set */
  531.         p = (uint8 *)qp->x;                    /* where question starts */
  532.         i = unpackdom(space,p,qp);                /* unpack question name */
  533. /*  spec defines name then  QTYPE + QCLASS = 4 bytes */
  534.         p += i+4;
  535. /*
  536. *  at this point, there may be several answers.  We will take the first
  537. *  one which has an IP number.  There may be other types of answers that
  538. *  we want to support later.
  539. */
  540.         while (nans-- > 0) {                    /* look at each answer */
  541.             i = unpackdom(space,p,qp);            /* answer name to unpack */
  542. /*            n_puts(space);*/
  543.             p += i;                                /* account for string */
  544.             rrp = (struct rrpart *)p;            /* resource record here */
  545. /*
  546. *  check things which might not align on 68000 chip one byte at a time
  547. */
  548.             if (!*p && *(p+1) == DTYPEA &&         /* correct type and class */
  549.                 !*(p+2) && *(p+3) == DIN) {
  550.                 movebytes(mip,rrp->rdata,4);    /* save IP #         */
  551.                 return(0);                        /* successful return */
  552.             }
  553.             movebytes(&j,&rrp->rdlength,2);        /* 68000 alignment */
  554.             p += 10+intswap(j);                    /* length of rest of RR */
  555.         }
  556.     }
  557.  
  558.     return(-1);                        /* generic failed to parse */
  559. }
  560.  
  561.  
  562. /***********************************************************************/
  563. static int son=1;
  564.  
  565. Scwritemode(mode)
  566.     int mode;
  567.     {
  568.         son = mode;
  569.         return(0);
  570. }
  571.  
  572. /***********************************************************************/
  573. Scmode()
  574.     {
  575.     return(son);
  576. }
  577.  
  578. /***********************************************************************/
  579. static int tekon=1;
  580.  
  581. Stekmode(mode)
  582.     int mode;
  583.     {
  584.         tekon = mode;
  585.         return(0);
  586. }
  587.  
  588. /***********************************************************************/
  589. Stmode()
  590.     {
  591.     return(tekon);
  592. }
  593.  
  594. /***********************************************************************/
  595. #ifdef PC
  596. static int rcpon=1;
  597.  
  598. Srcpmode(mode)
  599.     int mode;
  600.     {
  601.         rcpon = mode;
  602.         if (rcpon)
  603.             setrshd();
  604.         else
  605.             unsetrshd();
  606.         return(0);
  607. }
  608.  
  609. /***********************************************************************/
  610. Srmode()
  611.     {
  612.     return(rcpon);
  613. }
  614. #endif
  615.  
  616. /***********************************************************************/
  617. static int ftpon=0;
  618.  
  619. Sftpmode(mode)
  620.     int mode;
  621.     {
  622.         if (ftpon && mode)
  623.             return(-1);
  624.  
  625.         ftpon = mode;
  626.         if (ftpon)
  627.             setftp();
  628.         else
  629.             unsetftp();
  630.         return(0);
  631. }
  632.  
  633. /***********************************************************************/
  634. Sfmode()
  635.     {
  636.     return(ftpon);
  637. }
  638.  
  639. /***********************************************************************/
  640. /*  Snewcap
  641. *   set a new capture file name
  642. */
  643. Snewcap(s)
  644.     char *s;
  645.     {
  646.     if (NULL == (Scon.capture = (char *)NewPtr(strlen(s)+1)))
  647.         return(1);
  648.     strcpy(Scon.capture,s);
  649.     return(0);
  650. }
  651.  
  652. /***********************************************************************/
  653. /*  Snewps
  654. *   set a new ps file name
  655. */
  656. Snewpsfile(s)
  657.     char *s;
  658.     {
  659.     if (NULL == (Scon.psfile = (char *)NewPtr(strlen(s)+1)))
  660.         return(1);
  661.     strcpy(Scon.psfile,s);
  662.     return(0);
  663. }
  664.  
  665. /***********************************************************************/
  666. /*  Snewhpfile
  667. *   set a new HPGL file name
  668. */
  669. Snewhpfile(s)
  670.     char *s;
  671.     {
  672.     if (NULL == (Scon.hpfile = (char *)NewPtr(strlen(s)+1)))
  673.         return(1);
  674.     strcpy(Scon.hpfile,s);
  675.     return(0);
  676. }
  677.  
  678. /***********************************************************************/
  679. /*  Snewtekfile
  680. *   set a new tek file name
  681. */
  682. Snewtekfile(s)
  683.     char *s;
  684.     {
  685.     if (NULL == (Scon.tekfile = (char *)NewPtr(strlen(s)+1)))
  686.         return(1);
  687.     strcpy(Scon.tekfile,s);
  688.     return(0);
  689. }
  690.  
  691. /***********************************************************************/
  692. /*  Sopencap
  693. *   returns a file handle to an open capture file
  694. *   Uses the locally stored capture file name.
  695. */
  696. FILE *
  697. Sopencap()
  698.     {
  699.     FILE *retfp;
  700.  
  701.     if (NULL == (retfp = fopen(Scon.capture,"ab"))) 
  702.         return(NULL);
  703.  
  704.     fseek(retfp,0L,2);        /* seek to end */
  705.  
  706.     return(retfp);
  707. }
  708.  
  709. /**************************************************************************/
  710. /*  Stask
  711. *   A higher level version of netsleep
  712. *
  713. *   This manages the timer queue
  714. */
  715.  
  716. static int32 recent=0L;
  717.  
  718. Stask()
  719.     {
  720.     long t;
  721.     int i;
  722.  
  723. #ifndef APPLE_DRIVERS
  724.     netsleep(0);
  725. #endif APPLE_DRIVERS
  726.  
  727. /*
  728. *  Check the timer queue to see if something should be posted
  729. *  First check for timer wraparound
  730. */
  731.     t = time(NULL);
  732. #ifdef PC
  733.     if (t < recent) {
  734.         i = Stfirst;
  735.         while (i >= 0) {
  736.             Stq[i].when -= WRAPTIME;
  737.             i = Stq[i].next;
  738.         }
  739.     }
  740. #endif
  741.     recent = t;                            /* save most recent time */
  742.  
  743.     while (Stfirst >= 0 && t > Stq[Stfirst].when) {        
  744.                                 /* Q is not empty and timer is going off */
  745.         i = Stfirst;
  746.         netputevent(Stq[i].eclass,Stq[i].event,Stq[i].idata);
  747.         Stfirst = Stq[Stfirst].next;    /* remove from q */
  748.         Stq[i].next = Stfree;
  749.         Stfree = i;                        /* add to free list */
  750.     }
  751.  
  752.  
  753. }
  754.  
  755. /**************************************************************************/
  756. /*  Stimerset
  757. *  Sets an asynchronous timer which is checked in Stask()
  758. *  usage:
  759. *  Time is in seconds
  760. *  Stimerset(class,event,dat,time)
  761. *    int class,event,dat,time;
  762. *    class,event,dat is the event which should be posted at the specified
  763. *    time.  Accuracy is dependent on how often Stask is called.
  764. */
  765.  
  766. Stimerset(class,event,dat,howlong)
  767.     int class,event,dat,howlong;
  768.     {
  769.     int i,j,jlast,retval;
  770.     int32 gooff;
  771.  
  772.     retval = 0;
  773.     gooff = time(NULL) + howlong;
  774.  
  775.     if (Stfree < 0) {                /* queue is full, post first event */
  776.         Stfree = Stfirst;
  777.         Stfirst = Stq[Stfirst].next;
  778.         Stq[Stfree].next = -1;
  779.         netputevent(Stq[Stfree].eclass,Stq[Stfree].event,Stq[Stfree].idata);
  780.         retval = -1;
  781.     }
  782.  
  783.     Stq[Stfree].idata = dat;                /* event to occur at that time */
  784.     Stq[Stfree].event = event;
  785.     Stq[Stfree].eclass = class;
  786.     Stq[Stfree].when = gooff;
  787.     i = Stfree;                            /* remove from free list */
  788.     Stfree = Stq[i].next;
  789.  
  790.     if (Stfirst < 0) {                    /* if no queue yet */
  791.         Stfirst = i;
  792.         Stq[i].next = -1;                /* anchor active q */
  793.     }
  794.  
  795.     else if (gooff < Stq[Stfirst].when) {    /* goes first on list */
  796.         Stq[i].next = Stfirst;                /* at beginning of list */
  797.         Stfirst = i;
  798.     }
  799.  
  800.     else {                                    /* goes in middle */
  801.  
  802.         j = jlast = Stfirst;                /* search q from beginning */
  803.  
  804.         while (gooff >= Stq[j].when && j >= 0) {
  805.             jlast = j;
  806.             j = Stq[j].next;
  807.         }
  808.         Stq[i].next = j;                    /* insert in q */
  809.         Stq[jlast].next = i;
  810.     }
  811.  
  812.     return(retval);
  813. }
  814.  
  815. /****************************************************************************/
  816. /*  Stimerunset
  817. *   Remove all such timer events from the queue
  818. *   They must match all three fields, event, class and optional data
  819. *
  820. */
  821. Stimerunset(class,event,dat)
  822.     unsigned char event,class;
  823.     int dat;
  824.     {
  825.     int i,ilast,retval;
  826.  
  827.     retval = ilast = -1;
  828.     i = Stfirst;
  829.     while (i >= 0 ) {                    /* search list */
  830.  
  831.         if (Stq[i].idata == dat &&         /* this one matches */
  832.             Stq[i].eclass == class && Stq[i].event == event) {
  833.  
  834.             retval = 0;                    /* found at least one */
  835. /*
  836. * major bug fix -- if first element matched, old code could crash
  837. */
  838.             if (i == Stfirst) {
  839.                 Stfirst = Stq[i].next;            /* first one matches */
  840.                 Stq[i].next = Stfree;            /* attach to free list */
  841.                 Stfree = i;
  842.                 i = Stfirst;
  843.                 continue;                        /* start list over */
  844.             }
  845.             else {
  846.                 Stq[ilast].next = Stq[i].next;    /* remove this entry */
  847.                 Stq[i].next = Stfree;            /* attach to free list */
  848.                 Stfree = i;
  849.                 i = ilast;
  850.             }
  851.         }
  852.  
  853.         ilast = i;
  854.         i = Stq[i].next;
  855.     }
  856.  
  857.     return(retval);
  858. }
  859.  
  860. /****************************************************************************/
  861. /*  Scheckpass
  862. *   Check the password file for the user,password combination
  863. *   Returns valid or invalid
  864. */
  865. Scheckpass(us,ps)
  866.     char *us,*ps;
  867.     {
  868.     char buf[81],*p,*strchr();
  869.     FILE *fp;
  870.     
  871.     if (NULL == (fp = fopen(Scon.pass,"r"))) {
  872.     
  873. #ifdef MAC
  874. /*
  875. *  failed open, so try to find file in the system folder.
  876. */
  877.  
  878.         sysdir();                            /* change to system folder */
  879.         fp = fopen(Scon.pass,"r");
  880.         
  881.         setmydir();                            /* reset back to default dir */
  882.         
  883.         if (NULL == fp)                        /* still didn't work? */
  884. #endif
  885.             return(0);
  886.     }
  887.  
  888.     while (NULL != fgets(buf,80,fp)) {
  889.         p = strchr(buf,'\n');
  890.         *p = '\0';                            /* remove \n */
  891.  
  892.         p = strchr(buf,':');                /* find delimiter */
  893.         *p++ = '\0';
  894.         if (!strcmp(buf,us) &&            /* found user */
  895.             Scompass(ps,p)) {            /* does password check ?*/
  896.             fclose(fp);
  897.             return(1);
  898.         }
  899.     }
  900.  
  901.     fclose(fp);
  902.     return(0);
  903. }
  904.  
  905. /****************************************************************************/
  906. /* Sneedpass
  907. *  For other routines to call and find out if a password is required
  908. */
  909. Sneedpass()
  910.     {
  911.     if (Scon.pass == NULL)
  912.         return(0);
  913.  
  914.     return(1);
  915. }
  916.  
  917. /****************************************************************************/
  918. /* Scompass
  919. *  compute and check the encrypted password
  920. */
  921. Scompass(ps,en)
  922.     char *ps,*en;
  923.     {
  924.     int ck;
  925.     char *p,c;
  926.  
  927.     ck = 0;
  928.     p = ps;
  929.     while (*p)                /* checksum the string */
  930.         ck += *p++;
  931.  
  932.     c = ck;
  933.  
  934.     while (*en) {
  935.         if ((((*ps ^ c) | 32) & 127) != *en)    /* XOR with checksum */
  936.             return(0);
  937.         if (*ps)
  938.             ps++;
  939.         else
  940.             c++;            /* increment checksum to hide length */
  941.         en++;
  942.     }
  943.  
  944.     return(1);
  945. }
  946.  
  947. /****************************************************************************/
  948. /*  Sgetevent
  949. *   gets events from the network and filters those for session related
  950. *   activity.  Returns any other events to the caller.
  951. */
  952. Sgetevent(class,what,datp)
  953.     int class,*what,*datp;
  954.     {
  955.     int retval;
  956.  
  957.     if (retval = netgetevent(SCLASS,what,datp)) {    /* session event */
  958.         switch (retval) {
  959.             case FTPACT:
  960.                 ftpd(0,*datp);
  961.                 break;
  962. #ifdef PC
  963.             case RCPACT:                /* give CPU to rsh for rcp */
  964.                 rshd(0);
  965.                 break;
  966. #endif
  967. #ifdef MAC
  968.             case CLOSEDONE:                /* Used in the drivers */
  969.                 netclose( *datp);
  970.                 break;
  971.             case CLOSEDONE+1:                /* Used in the drivers */
  972.                 netclose( *datp);
  973.                 break;
  974. #endif MAC
  975.             case UDPTO:                    /* name server not responding */
  976.                 domto(*datp);
  977.                 break;
  978.             case RETRYCON:
  979.                 if (0 < netopen2(*datp))     /* connection open yet? */
  980.                     Stimerset(SCLASS,RETRYCON,*datp,4);  /* 4 is a kludge */
  981.                 break;
  982.  
  983.             default:
  984.                 break;
  985.         }
  986.     }
  987.  
  988.     Stask();                        /* allow net and timers to take place */
  989.  
  990.     if (!(retval = netgetevent(class,what,datp)))
  991.         return(0);
  992.         
  993.     if (retval == CONOPEN) 
  994.         Stimerunset(CONCLASS,CONFAIL,*datp);   /* kill this timer */
  995.  
  996.     if ((*datp == 997) && (retval == UDPDATA)) {
  997.         udpdom();
  998.     }
  999.     else if ((*what == CONCLASS) && (Sptypes[*datp] >= 0)) {
  1000.                                         /* might be for session layer */
  1001.         switch (Sptypes[*datp]) {
  1002.             case PFTP:
  1003.                 rftpd(retval);
  1004.                 break;
  1005.             case PDATA:
  1006.                 ftpd(retval,*datp);
  1007.                 break;
  1008. #ifdef PC
  1009.             case PRCP:
  1010.                 rshd(retval);
  1011.                 break;
  1012. #endif
  1013.             default:
  1014.                 break;
  1015.         }
  1016.     }
  1017.     else
  1018.         return(retval);                /* let higher layer have it */
  1019.  
  1020.     return(0);
  1021. }
  1022.  
  1023.